home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Languguage OS 2
/
Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO
/
gnu
/
less_237.zip
/
less_237
/
doscreen.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-09-26
|
11KB
|
572 lines
/*
* Copyright (c) 1984,1985,1989,1994 Mark Nudelman
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice in the documentation and/or other materials provided with
* the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Routines which deal with the characteristics of the terminal.
*
* This file is specific to MS-DOS and uses Microsoft C graphics functions.
*/
#include "less.h"
#include "cmd.h"
#include <graph.h>
#include <time.h>
static int init_done = 0;
static int videopages;
static long msec_loops;
public int auto_wrap; /* Terminal does \r\n when write past margin */
public int ignaw; /* Terminal ignores \n immediately after wrap */
public int erase_char, kill_char; /* The user's erase and line-kill chars */
public int sc_width, sc_height; /* Height & width of screen */
public int bo_s_width, bo_e_width; /* Printing width of boldface seq */
public int ul_s_width, ul_e_width; /* Printing width of underline seq */
public int so_s_width, so_e_width; /* Printing width of standout seq */
public int bl_s_width, bl_e_width; /* Printing width of blink seq */
public int nm_fg_color = 7; /* Color of normal text */
public int nm_bg_color = 0;
public int bo_fg_color = 15; /* Color of bold text */
public int bo_bg_color = 0;
public int ul_fg_color = 9; /* Color of underlined text */
public int ul_bg_color = 0;
public int so_fg_color = 0; /* Color of standout text */
public int so_bg_color = 7;
public int bl_fg_color = 12; /* Color of blinking text */
public int bl_bg_color = 0;
static int sy_fg_color;
static int sy_bg_color;
static int flash_created = 0;
extern int quiet; /* If VERY_QUIET, use visual bell for bell */
extern int know_dumb; /* Don't complain about a dumb terminal */
extern int back_scroll;
extern int swindow;
extern char *getenv();
/*
* Change terminal to "raw mode", or restore to "normal" mode.
* "Raw mode" means
* 1. An outstanding read will complete on receipt of a single keystroke.
* 2. Input is not echoed.
* 3. On output, \n is mapped to \r\n.
* 4. \t is NOT expanded into spaces.
* 5. Signal-causing characters such as ctrl-C (interrupt),
* etc. are NOT disabled.
* It doesn't matter whether an input \n is mapped to \r, or vice versa.
*/
public void
raw_mode(on)
int on;
{
static int curr_on = 0;
if (on == curr_on)
return;
erase_char = CONTROL('h');
kill_char = '\33'; /* ESC */
curr_on = on;
}
/*
* Get size of the output screen.
*/
public void
scrsize(p_height, p_width)
int *p_height;
int *p_width;
{
register char *s;
struct videoconfig w;
_getvideoconfig(&w);
if (w.numtextrows)
*p_height = w.numtextrows;
else if ((s = getenv("LINES")) != NULL && *s != '\0')
*p_height = atoi(s);
if (*p_height <= 0)
*p_height = 24;
if (w.numtextcols > 0)
*p_width = w.numtextcols;
else if ((s = getenv("COLUMNS")) != NULL)
*p_width = atoi(s);
if (*p_width <= 0)
*p_width = 80;
}
/*
* Figure out how many empty loops it takes to delay a millisecond.
*/
static void
get_clock()
{
clock_t start;
/*
* Get synchronized at the start of a tick.
*/
start = clock();
while (clock() == start)
;
/*
* Now count loops till the next tick.
*/
start = clock();
msec_loops = 0;
while (clock() == start)
msec_loops++;
/*
* Convert from (loops per clock) to (loops per millisecond).
*/
msec_loops *= CLOCKS_PER_SEC;
msec_loops /= 1000;
}
public void
get_editkeys()
{
}
/*
* Get terminal capabilities via termcap.
*/
public void
get_term()
{
scrsize(&sc_height, &sc_width);
pos_init();
auto_wrap = 1;
ignaw = 0;
so_e_width = so_s_width = 0;
bo_s_width = bo_e_width = 0;
ul_s_width = ul_e_width = 0;
bl_s_width = bl_e_width = 0;
get_clock();
}
/*
* Below are the functions which perform all the
* terminal-specific screen manipulation.
*/
/*
* Initialize terminal
*/
public void
init()
{
/* {{ What could we take no_init (-X) to mean? }} */
sy_bg_color = _getbkcolor();
sy_fg_color = _gettextcolor();
flush();
init_done = 1;
}
/*
* Create an alternate screen which is all white.
* This screen is used to create a "flash" effect, by displaying it
* briefly and then switching back to the normal screen.
* {{ Yuck! There must be a better way to get a visual bell. }}
*/
static void
create_flash()
{
struct videoconfig w;
char *blanks;
int row, col;
_getvideoconfig(&w);
videopages = w.numvideopages;
if (videopages < 2)
{
so_enter();
so_exit();
} else
{
_setactivepage(1);
so_enter();
blanks = (char *) ecalloc(w.numtextcols, sizeof(char));
for (col = 0; col < w.numtextcols; col++)
blanks[col] = ' ';
for (row = w.numtextrows; row > 0; row--)
_outmem(blanks, w.numtextcols);
_setactivepage(0);
_setvisualpage(0);
free(blanks);
so_exit();
}
flash_created = 1;
}
/*
* Deinitialize terminal
*/
public void
deinit()
{
if (!init_done)
return;
_setbkcolor(sy_bg_color);
_settextcolor(sy_fg_color);
putstr("\n");
init_done = 0;
}
/*
* Home cursor (move to upper left corner of screen).
*/
public void
home()
{
flush();
_settextposition(1,1);
}
/*
* Add a blank line (called with cursor at home).
* Should scroll the display down.
*/
public void
add_line()
{
flush();
_scrolltextwindow(_GSCROLLDOWN);
_settextposition(1,1);
}
/*
* Move cursor to lower left corner of screen.
*/
public void
lower_left()
{
flush();
_settextposition(sc_height,1);
}
/*
* Delay for a specified number of milliseconds.
*/
static void
dummy_func()
{
static long delay_dummy = 0;
delay_dummy++;
}
static void
delay(msec)
int msec;
{
long i;
while (msec-- > 0)
{
for (i = 0; i < msec_loops; i++)
{
/*
* Make it look like we're doing something here,
* so the optimizer doesn't remove the whole loop.
*/
dummy_func();
}
}
}
/*
* Make a noise.
*/
static void
beep()
{
write(1, "\7", 1);
}
/*
* Output the "visual bell", if there is one.
*/
public void
vbell()
{
if (!flash_created)
/*
* Create a "flash" on the second video page.
*/
create_flash();
if (videopages < 2)
/*
* There is no "second video page".
*/
return;
_setvisualpage(1);
/*
* Leave it displayed for 100 msec.
*/
delay(100);
_setvisualpage(0);
}
/*
* Ring the terminal bell.
*/
public void
bell()
{
if (quiet == VERY_QUIET)
vbell();
else
beep();
}
/*
* Clear the screen.
*/
public void
clear()
{
flush();
_clearscreen(_GCLEARSCREEN);
}
/*
* Clear from the cursor to the end of the cursor's line.
* {{ This must not move the cursor. }}
*/
public void
clear_eol()
{
short top, left;
short bot, right;
struct rccoord tpos;
flush();
/*
* Save current state.
*/
tpos = _gettextposition();
_gettextwindow(&top, &left, &bot, &right);
/*
* Set a temporary window to the current line,
* from the cursor's position to the right edge of the screen.
* Then clear that window.
*/
_settextwindow(tpos.row, tpos.col, tpos.row, sc_width);
_clearscreen(_GWINDOW);
/*
* Restore state.
*/
_settextwindow(top, left, bot, right);
_settextposition(tpos.row, tpos.col);
}
/*
* Clear the bottom line of the display.
* Leave the cursor at the beginning of the bottom line.
*/
public void
clear_bot()
{
lower_left();
clear_eol();
}
/*
* Begin "standout" (bold, underline, or whatever).
*/
public void
so_enter()
{
flush();
_setbkcolor(so_bg_color);
_settextcolor(so_fg_color);
}
/*
* End "standout".
*/
public void
so_exit()
{
flush();
_setbkcolor(nm_bg_color);
_settextcolor(nm_fg_color);
}
/*
* Begin "underline" (hopefully real underlining,
* otherwise whatever the terminal provides).
*/
public void
ul_enter()
{
flush();
_setbkcolor(ul_bg_color);
_settextcolor(ul_fg_color);
}
/*
* End "underline".
*/
public void
ul_exit()
{
flush();
_setbkcolor(nm_bg_color);
_settextcolor(nm_fg_color);
}
/*
* Begin "bold"
*/
public void
bo_enter()
{
flush();
_setbkcolor(bo_bg_color);
_settextcolor(bo_fg_color);
}
/*
* End "bold".
*/
public void
bo_exit()
{
flush();
_setbkcolor(nm_bg_color);
_settextcolor(nm_fg_color);
}
/*
* Begin "blink"
*/
public void
bl_enter()
{
flush();
_setbkcolor(bl_bg_color);
_settextcolor(bl_fg_color);
}
/*
* End "blink".
*/
public void
bl_exit()
{
flush();
_setbkcolor(nm_bg_color);
_settextcolor(nm_fg_color);
}
/*
* Erase the character to the left of the cursor
* and move the cursor left.
*/
public void
backspace()
{
struct rccoord tpos;
/*
* Erase the previous character by overstriking with a space.
*/
flush();
tpos = _gettextposition();
if (tpos.col <= 1)
return;
_settextposition(tpos.row, tpos.col-1);
_outtext(" ");
_settextposition(tpos.row, tpos.col-1);
}
/*
* Output a plain backspace, without erasing the previous char.
*/
public void
putbs()
{
struct rccoord tpos;
flush();
tpos = _gettextposition();
if (tpos.col <= 1)
return;
_settextposition(tpos.row, tpos.col-1);
}
/*
* Table of line editting characters, for editchar() in decode.c.
*/
char edittable[] = {
'\340','\115',0, EC_RIGHT, /* RIGHTARROW */
'\340','\113',0, EC_LEFT, /* LEFTARROW */
'\340','\163',0, EC_W_LEFT, /* CTRL-LEFTARROW */
'\340','\164',0, EC_W_RIGHT, /* CTRL-RIGHTARROW */
'\340','\122',0, EC_INSERT, /* INSERT */
'\340','\123',0, EC_DELETE, /* DELETE */
'\340','\223',0, EC_W_DELETE, /* CTRL-DELETE */
'\177',0, EC_W_BACKSPACE, /* CTRL-BACKSPACE */
'\340','\107',0, EC_HOME, /* HOME */
'\340','\117',0, EC_END, /* END */
'\340','\110',0, EC_UP, /* UPARROW */
'\340','\120',0, EC_DOWN, /* DOWNARROW */
'\t',0, EC_F_COMPLETE, /* TAB */
'\17',0, EC_B_COMPLETE, /* BACKTAB (?) */
'\340','\17',0, EC_B_COMPLETE, /* BACKTAB */
'\14',0, EC_EXPAND, /* CTRL-L */
0 /* Extra byte to terminate; subtracted from size, below */
};
int sz_edittable = sizeof(edittable) -1;
char kcmdtable[] =
{
/*
* PC function keys.
* Note that '\0' is converted to '\340' on input.
*/
'\340','\120',0, A_F_LINE, /* down arrow */
'\340','\121',0, A_F_SCREEN, /* page down */
'\340','\110',0, A_B_LINE, /* up arrow */
'\340','\111',0, A_B_SCREEN, /* page up */
'\340','\107',0, A_GOLINE, /* home */
'\340','\117',0, A_GOEND, /* end */
'\340','\073',0, A_HELP, /* F1 */
'\340','\022',0, A_EXAMINE, /* Alt-E */
0
};
int sz_kcmdtable = sizeof(kcmdtable) - 1;